package zdream.pmfield.test.stage;

import org.junit.Before;
import org.junit.Test;

import java.util.List;

import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.Type;
import zdream.pmfield.stage.Stage;
import zdream.pmfield.stage.buff.foe.TypeBuff;
import zdream.pmfield.stage.message.ActionRequestMessage;
import zdream.pmfield.stage.message.ActionRequestReply;
import zdream.pmfield.stage.message.StageMessage;
import zdream.pmfield.stage.object.FoeActor;
import zdream.pmfield.stage.object.Seat;
import zdream.pmfield.storage.FoeTemplateStorage;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-11-10
 * @since 0.0.1
 */
public class StageCase {
	FoeTemplateStorage storage;
	Foe foe1, foe2;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();

		foe1 = Foe.builder(storage.findFoeById(1))
				.withLevel(20)
				.build();
		foe2 = Foe.builder(storage.findFoeById(4))
				.withLevel(20)
				.build();
	}

	@Test
	public void testCreateStage() {
		Stage stage = Stage.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.build();
		final Seat[] seats = stage.seats;
		assertEquals(seats.length, 5);

		assertEquals(seats[0].right, seats[1]);
		assertEquals(seats[1].right, seats[2]);
		assertEquals(seats[2].right, seats[3]);
		assertEquals(seats[3].right, seats[4]);
		assertNull(seats[4].right);

		assertEquals(seats[4].left, seats[3]);
		assertEquals(seats[3].left, seats[2]);
		assertEquals(seats[2].left, seats[1]);
		assertEquals(seats[1].left, seats[0]);
		assertNull(seats[0].left);

		final List<FoeActor> seat1Foes = seats[1].findFoes();
		assertNotNull(seat1Foes);
		assertEquals(seat1Foes.size(), 1);
		final FoeActor seat1Foe = seat1Foes.get(0);
		assertEquals(seat1Foe.foe, foe1);

		final List<FoeActor> seat3Foes = seats[3].findFoes();
		assertNotNull(seat3Foes);
		assertEquals(seat3Foes.size(), 1);
		final FoeActor seat3Foe = seat3Foes.get(0);
		assertEquals(seat3Foe.foe, foe2);

		assertFalse(seat1Foe.buffs.isEmpty());
		for (Type type : foe1.template.types) {
			boolean exists = seat1Foe.buffs.stream()
					.filter(b -> b.is(Type.TYPE))
					.map(b -> (TypeBuff) b)
					.anyMatch(b -> b.type == type);
			assertTrue(exists);
		}
		for (Type type : foe2.template.types) {
			boolean exists = seat3Foe.buffs.stream()
					.filter(b -> b.is(Type.TYPE))
					.map(b -> (TypeBuff) b)
					.anyMatch(b -> b.type == type);
			assertTrue(exists);
		}
	}

	@Test
	public void testGetMessageWithoutReply() {
		Stage stage = Stage.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.build();
		boolean completed = false;
		int needReplyCount = 0;
		int messageTotal = 0;

		System.out.println("TEST 1: run stage without replying message");
		while (!completed) {
			final StageMessage message = stage.run();
			assertNotNull(message);

			++messageTotal;
			assertTrue(messageTotal < 50);

			if (needReplyCount > 0) {
				assertTrue(message.needReply());
			}

			// needReply 的 message 一直不回复的话, 返回的一直是这个 message
			if (message.needReply()) {
				++needReplyCount;
				completed = needReplyCount > 9;
			}
		}

		System.out.println("TEST 2: run stage with replying message fail");
		StageMessage message1 = stage.run();
		assertTrue(message1.needReply());
		assertTrue(message1 instanceof ActionRequestMessage);

		final ActionRequestMessage request1 = (ActionRequestMessage) message1;
		final ActionRequestReply replyTemplate = request1.createReplyTemplate();
		assertFalse(request1.commit(replyTemplate).success);

		StageMessage message2 = stage.run();
		assertTrue(message2.needReply());
		assertTrue(message2 instanceof ActionRequestMessage);

		final ActionRequestMessage request2 = (ActionRequestMessage) message2;
		assertEquals(request1.foe, request2.foe);
		assertEquals(request1.type, request2.type);
	}
}
